package aiku.numericalcontroloa.Service.FinanceManagement.Impl;

import aiku.numericalcontroloa.Base.Utils.HttpStatus;
import aiku.numericalcontroloa.Base.Utils.Result;
import aiku.numericalcontroloa.Mapper.*;
import aiku.numericalcontroloa.Mapper.FinanceManagement.AccountMapper;
import aiku.numericalcontroloa.Mapper.FinanceManagement.IncomeExpenditureDetailMapper;
import aiku.numericalcontroloa.Mapper.OrderManagement.OrderBillingMapper;
import aiku.numericalcontroloa.Mapper.OrderManagement.OrderMapper;
import aiku.numericalcontroloa.Model.Dto.FinanceManagement.AccountDto;
import aiku.numericalcontroloa.Model.Dto.FinanceManagement.IncomeExpenditureDetailDto;
import aiku.numericalcontroloa.Model.Entity.*;
import aiku.numericalcontroloa.Model.Entity.FinanceManagement.Account;
import aiku.numericalcontroloa.Model.Entity.FinanceManagement.IncomeExpenditureDetail;
import aiku.numericalcontroloa.Model.Entity.OrderManagement.Order;
import aiku.numericalcontroloa.Model.Entity.OrderManagement.OrderBilling;
import aiku.numericalcontroloa.Model.Vo.FinanceManagement.AccountVo;
import aiku.numericalcontroloa.Model.Vo.FinanceManagement.IncomeExpenditureDetailVo;
import aiku.numericalcontroloa.Service.FinanceManagement.AccountService;
import aiku.numericalcontroloa.common.utils.DateUtils;
import aiku.numericalcontroloa.enums.RoleEnum;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author 黄广庭
 * @Date 2024/5/7 12:05
 */
@Service
public class AccountServiceImpl implements AccountService {
    private final AccountMapper accountMapper;
    private final UserMapper userMapper;
    private final OrderMapper orderMapper;
    private final OrderBillingMapper orderBillingMapper;
    private final IncomeExpenditureDetailMapper detailMapper;
    private final ClientsMapper clientsMapper;
    private final PaymentBillingMapper paymentBillingMapper;
    private final PurchaseOrdersMapper purchaseOrdersMapper;
    private final SuppliersMapper suppliersMapper;
    private final ExpenseMapper expenseMapper;

    public AccountServiceImpl(AccountMapper accountMapper, UserMapper userMapper, OrderMapper orderMapper,
            OrderBillingMapper orderBillingMapper, IncomeExpenditureDetailMapper detailMapper,
            ClientsMapper clientsMapper, PaymentBillingMapper paymentBillingMapper,
            PurchaseOrdersMapper purchaseOrdersMapper, SuppliersMapper suppliersMapper, ExpenseMapper expenseMapper) {
        this.accountMapper = accountMapper;
        this.userMapper = userMapper;
        this.orderMapper = orderMapper;
        this.orderBillingMapper = orderBillingMapper;
        this.detailMapper = detailMapper;
        this.clientsMapper = clientsMapper;
        this.paymentBillingMapper = paymentBillingMapper;
        this.purchaseOrdersMapper = purchaseOrdersMapper;
        this.suppliersMapper = suppliersMapper;
        this.expenseMapper = expenseMapper;
    }

    @Override
    public Result addAccount(AccountDto accountDto) {
        if (accountDto == null) {
            return new Result(HttpStatus.BAD_REQUEST, "缺少参数");
        }
        // 权限判断
        User user = userMapper.selectById(StpUtil.getLoginIdAsString());
        boolean flag = user.getRoleId().equals(RoleEnum.ROLE_1.getCodeToString()) ||
                user.getRoleId().equals(RoleEnum.ROLE_6.getCodeToString());
        // 不等于管理员和财务的没有权限添加
        if (!flag) {
            return new Result(HttpStatus.FORBIDDEN, "无权限添加");
        }
        // 添加账号
        Account account = new Account();
        if (accountDto.getAccountName() == null || accountDto.getAccountName().isEmpty()) {
            return new Result(HttpStatus.BAD_REQUEST, "缺少参数");
        }
        account.setAccountName(accountDto.getAccountName());
        if (accountDto.getAccount() == null || accountDto.getAccount().isEmpty()) {
            return new Result(HttpStatus.BAD_REQUEST, "缺少参数");
        }
        account.setAccount(accountDto.getAccount());
        if (accountDto.getBalance() == null) {
            return new Result(HttpStatus.BAD_REQUEST, "缺少参数");
        }
        account.setBalance(accountDto.getBalance());
        account.setAccountRemark(accountDto.getAccountRemark());
        accountMapper.insert(account);
        return Result.success("添加成功");
    }

    @Override
    public Result updateAccount(AccountDto accountDto) {
        if (accountDto == null || accountDto.getId() == null || accountDto.getId().isEmpty()) {
            return new Result(HttpStatus.BAD_REQUEST, "缺少参数");
        }
        // 是否有权限修改
        // 只有超级管理员可以修改
        User user = userMapper.selectById(StpUtil.getLoginIdAsString());
        if (!user.getRoleId().equals(RoleEnum.ROLE_1.getCodeToString())) {
            return new Result(HttpStatus.FORBIDDEN, "权限不足");
        }
        // 查询是否有该账号
        Account account = accountMapper.selectById(accountDto.getId());
        if (account == null) {
            return new Result(HttpStatus.BAD_REQUEST, "参数错误");
        }
        // 修改开户名
        if (accountDto.getAccountName() != null && !accountDto.getAccountName().isEmpty()) {
            account.setAccountName(accountDto.getAccountName());
        }
        // 修改账号
        if (accountDto.getAccount() != null && !accountDto.getAccount().isEmpty()) {
            account.setAccount(accountDto.getAccount());
        }
        // 修改金额
        if (accountDto.getBalance() != null) {
            account.setBalance(accountDto.getBalance());
        }
        // 修改备注
        if (accountDto.getAccountRemark() != null && !accountDto.getAccountRemark().isEmpty()) {
            account.setAccountRemark(accountDto.getAccountRemark());
        }
        // 更新数据
        accountMapper.updateById(account);
        return Result.success("修改成功");
    }

    @Override
    public Result getAccountDetailList(AccountDto accountDto) {
        if (accountDto == null || (accountDto.getCurrentPage() == null && accountDto.getPageSize() == null)) {
            return new Result(HttpStatus.BAD_REQUEST, "缺少参数");
        }
        Page<Account> accountPage = new Page<>(accountDto.getCurrentPage(), accountDto.getPageSize());
        // 条件查询
        LambdaQueryWrapper<Account> accountLQW = new LambdaQueryWrapper<>();
        accountLQW.orderByDesc(Account::getCreateTime);
        // 根据开户名或账号模糊查询
        if (accountDto.getAccountName() != null && !accountDto.getAccountName().isEmpty()) {
            accountLQW.like(Account::getAccountName, accountDto.getAccountName())
                    .or()
                    .like(Account::getAccount, accountDto.getAccountName())
                    .orderByDesc(Account::getCreateTime);
        }
        List<Account> accountList = accountMapper.selectPage(accountPage, accountLQW).getRecords();
        List<Account> orderBillingAllList = accountMapper.selectList(accountLQW);
        BigDecimal totalAmount = new BigDecimal(0);
        Map<String, Object> map = new HashMap<>();
        List<AccountVo> accountVoList = new ArrayList<>();
        if (accountList.isEmpty()) {
            map.put("total", 0);
            map.put("totalAmount", totalAmount);
            map.put("accountVoList", accountVoList);
            return Result.success("查询成功", map);
        }

        Map<String, Account> accountMap = accountList.stream()
                .collect(Collectors.toMap(Account::getId, a -> accountList.stream()
                        .filter(account -> account.getId().equals(a.getId()))
                        .findFirst()
                        .orElse(null)));
        List<String> accountIdList = accountList.stream().map(Account::getId).collect(Collectors.toList());

        // 根据账户查询账单
        // 根据日期查询
        // 付款/报销账单
        LambdaQueryWrapper<PaymentBilling> paymentBillingLQW = new LambdaQueryWrapper<>();
        paymentBillingLQW.in(PaymentBilling::getAccount, accountIdList);
        // 收款账单
        LambdaQueryWrapper<OrderBilling> orderBillingLQW = new LambdaQueryWrapper<>();
        orderBillingLQW.in(OrderBilling::getAccount, accountIdList);
        if (accountDto.getYear() != null) {
            // 付款
            paymentBillingLQW.apply("YEAR(payment_date) = {0}", accountDto.getYear());
            // 收款
            orderBillingLQW.apply("YEAR(date_received) = {0}", accountDto.getYear());
        }
        if (accountDto.getYearMonth() != null) {
            // 付款
            paymentBillingLQW.apply("DATE_FORMAT(payment_date, '%Y-%m') = {0}", accountDto.getYearMonth());
            // 收款
            orderBillingLQW.apply("DATE_FORMAT(date_received, '%Y-%m') = {0}", accountDto.getYearMonth());
        }
        if (accountDto.getYearMonthDay() != null) {
            // 付款
            paymentBillingLQW.apply("DATE(payment_date) = {0}", accountDto.getYearMonthDay());
            // 收款
            orderBillingLQW.apply("DATE(date_received) = {0}", accountDto.getYearMonthDay());
        }
        // 付款账单
        List<PaymentBilling> paymentBillingList = paymentBillingMapper.selectList(paymentBillingLQW);
        Map<String, List<PaymentBilling>> paymentBillingMap = new HashMap<>();
        for (PaymentBilling paymentBilling : paymentBillingList) {
            if (paymentBillingMap.containsKey(paymentBilling.getAccount())) {
                paymentBillingMap.get(paymentBilling.getAccount()).add(paymentBilling);
            } else {
                List<PaymentBilling> billingList = new ArrayList<>();
                billingList.add(paymentBilling);
                paymentBillingMap.put(paymentBilling.getAccount(), billingList);
            }
        }
        // 收款账单
        List<OrderBilling> orderBillingList = orderBillingMapper.selectList(orderBillingLQW);
        Map<String, List<OrderBilling>> orderBillingMap = new HashMap<>();
        for (OrderBilling orderBilling : orderBillingList) {
            if (orderBillingMap.containsKey(orderBilling.getAccount())) {
                orderBillingMap.get(orderBilling.getAccount()).add(orderBilling);
            } else {
                List<OrderBilling> billingList = new ArrayList<>();
                billingList.add(orderBilling);
                orderBillingMap.put(orderBilling.getAccount(), billingList);
            }
        }

        for (Account account : accountList) {
            AccountVo accountVo = new AccountVo();
            BeanUtils.copyProperties(account, accountVo);
            // 支出
            BigDecimal disburse = new BigDecimal(0);
            if (paymentBillingMap.containsKey(account.getId())) {
                for (PaymentBilling paymentBilling : paymentBillingMap.get(account.getId())) {
                    disburse = disburse.add(paymentBilling.getPaymentAmount());
                }
            }
            accountVo.setDisburse(disburse);
            // 收入
            BigDecimal income = new BigDecimal(0);
            if (orderBillingMap.containsKey(account.getId())) {
                for (OrderBilling orderBilling : orderBillingMap.get(account.getId())) {
                    income = income.add(orderBilling.getFundsReceived());
                }
            }
            accountVo.setIncome(income);
            accountVoList.add(accountVo);
        }
        for (Account orderBilling : orderBillingAllList) {
            totalAmount = totalAmount.add(orderBilling.getBalance());
        }
        map.put("total", accountPage.getTotal());
        map.put("totalAmount", totalAmount);
        map.put("accountVoList", accountVoList);
        return Result.success("查询成功", map);
    }

    @Override
    public Result getAccount(AccountDto accountDto) {
        if (accountDto == null || accountDto.getId() == null) {
            return new Result(HttpStatus.BAD_REQUEST, "缺少参数");
        }
        Account account = accountMapper.selectById(accountDto.getId());
        if (account == null) {
            return new Result(HttpStatus.BAD_REQUEST, "该账户不存在");
        }
        AccountVo accountVo = new AccountVo();
        BeanUtils.copyProperties(account, accountVo);
        return Result.success("查询成功", accountVo);
    }

    @Override
    public Result getAccountList(AccountDto accountDto) {
        if (accountDto == null || (accountDto.getCurrentPage() == null && accountDto.getPageSize() == null)) {
            return new Result(HttpStatus.BAD_REQUEST, "缺少参数");
        }
        Page<Account> accountPage = new Page<>(accountDto.getCurrentPage(), accountDto.getPageSize());
        // 根据开户名和账户模糊查询
        LambdaQueryWrapper<Account> accountLQW = new LambdaQueryWrapper<>();
        if (accountDto.getAccountName() != null && !accountDto.getAccountName().isEmpty()) {
            accountLQW.like(Account::getAccountName, accountDto.getAccountName())
                    .or().like(Account::getAccount, accountDto.getAccountName());
        }
        List<Account> accountList = accountMapper.selectPage(accountPage, accountLQW).getRecords();
        Map<String, Object> map = new HashMap<>();
        map.put("total", accountPage.getTotal());
        map.put("accountList", accountList);
        return Result.success("查询成功", map);
    }

    @Override
    public Result deleteAccount(AccountDto accountDto) {
        if (accountDto == null || accountDto.getId() == null) {
            return new Result(HttpStatus.BAD_REQUEST, "缺少参数");
        }
        // 权限判断
        User user = userMapper.selectById(StpUtil.getLoginIdAsString());
        if (!user.getRoleId().equals(RoleEnum.ROLE_1.getCodeToString())) {
            return new Result(HttpStatus.FORBIDDEN, "无权限");
        }
        // 是否有该账户
        Account account = accountMapper.selectById(accountDto.getId());
        if (account == null) {
            return new Result(HttpStatus.BAD_REQUEST, "该账户不存在");
        }
        // 删除
        accountMapper.deleteById(account.getId());
        return Result.success("删除成功");
    }

    @Override
    public Result getAccountIncomeExpenditureDetailList(IncomeExpenditureDetailDto detailDto) {
        if (detailDto == null) {
            return new Result(HttpStatus.BAD_REQUEST, "参数为空(detailDto is null)");
        }
        if (detailDto.getAccountId() == null || detailDto.getAccountId().isEmpty()) {
            return new Result(HttpStatus.BAD_REQUEST, "参数为空(detailDto[accountId] is null)");
        }
        if (detailDto.getCurrentPage() == null || detailDto.getPageSize() == null) {
            return new Result(HttpStatus.BAD_REQUEST, "分页参数为空");
        }
        Page<IncomeExpenditureDetail> detailPage = new Page<>(detailDto.getCurrentPage(), detailDto.getPageSize());
        // 查询是否有该账户
        Account account = accountMapper.selectById(detailDto.getAccountId());
        if (account == null) {
            return new Result(HttpStatus.BAD_REQUEST, "该账户不存在");
        }
        // 条件查询
        LambdaQueryWrapper<IncomeExpenditureDetail> detailDtoLQW = new LambdaQueryWrapper<>();
        detailDtoLQW.eq(IncomeExpenditureDetail::getAccountId, account.getId())
                .orderByDesc(IncomeExpenditureDetail::getCreateTime);
        if (detailDto.getDetailType() != null) {
            // 根据明细类型查询
            detailDtoLQW.eq(IncomeExpenditureDetail::getDetailType, detailDto.getDetailType());
        }
        if (detailDto.getYear() != null) {
            // 根据年查询
            detailDtoLQW.apply("YEAR(trading_hours) = {0}", detailDto.getYear());
        }
        if (detailDto.getYearMonth() != null) {
            // 根据月查询
            detailDtoLQW.apply("DATE_FORMAT(trading_hours, '%Y-%m') = {0}", detailDto.getYearMonth());
        }
        if (detailDto.getYearMonthDay() != null) {
            // 根据日查询
            detailDtoLQW.apply("DATE(trading_hours) = {0}", detailDto.getYearMonthDay());
        }
        List<IncomeExpenditureDetail> detailList = detailMapper.selectPage(detailPage, detailDtoLQW).getRecords();

        // id
        List<String> paymentBillingIdList = new ArrayList<>();
        List<String> expenseBillingIdList = new ArrayList<>();
        List<String> orderBillingIdList = new ArrayList<>();
        if (detailList.size() > 0) {
            // 支付账单
            paymentBillingIdList = detailList.stream().filter(d -> d.getDetailType().equals(0))
                    .map(IncomeExpenditureDetail::getExpenseId)
                    .collect(Collectors.toList());
            // 报销账单
            expenseBillingIdList = detailList.stream().filter(d -> d.getDetailType().equals(1))
                    .map(IncomeExpenditureDetail::getExpenseId)
                    .collect(Collectors.toList());
            // 付款账单
            orderBillingIdList = detailList.stream().filter(d -> d.getDetailType().equals(2))
                    .map(IncomeExpenditureDetail::getExpenseId)
                    .collect(Collectors.toList());
        }
        // 根据id查询其他账单
        // 付款
        Map<String, PaymentBilling> paymentBillingMap = new HashMap<>();
        // 根据账单id获取供应商对象
        Map<String, Suppliers> suppliersMap = new HashMap<>();
        if (paymentBillingIdList.size() > 0) {
            // 付款账单
            List<PaymentBilling> paymentBillingList = paymentBillingMapper.selectBatchIds(paymentBillingIdList);
            Set<String> orderIdList;
            if (paymentBillingList.size() > 0) {
                paymentBillingMap = paymentBillingList.stream().collect(Collectors.toMap(PaymentBilling::getId,
                        p -> paymentBillingList.stream()
                                .filter(paymentBilling -> paymentBilling.getId().equals(p.getId()))
                                .findFirst()
                                .orElse(null)));
                orderIdList = paymentBillingList.stream().map(PaymentBilling::getOrderId).collect(Collectors.toSet());
                // 查采购订单
                List<PurchaseOrders> purchaseOrdersList = purchaseOrdersMapper.selectBatchByIdWithDelete(orderIdList);
                Set<String> suppliersIdList = purchaseOrdersList.stream().map(PurchaseOrders::getSuppliersId)
                        .collect(Collectors.toSet());
                // 查供应商
                List<Suppliers> suppliersList = suppliersMapper.selectBatchByIdWithDelete(suppliersIdList);
                suppliersMap = paymentBillingList.stream().collect(Collectors.toMap(PaymentBilling::getId,
                        paymentBilling -> purchaseOrdersList.stream()
                                .filter(order -> order.getId().equals(paymentBilling.getOrderId()))
                                .findFirst()
                                .flatMap(order -> suppliersList.stream()
                                        .filter(suppliers -> suppliers.getId().equals(order.getSuppliersId()))
                                        .findFirst())
                                .orElse(null)));
            }
        }
        // 报销
        Map<String, PaymentBilling> expenseBillingMap = new HashMap<>();
        Map<String, User> userMap = new HashMap<>();
        if (expenseBillingIdList.size() > 0) {
            // 报销账单
            List<PaymentBilling> expenseBillingList = paymentBillingMapper.selectBatchIds(expenseBillingIdList);
            Set<String> expenseIdList;
            if (expenseBillingList.size() > 0) {
                expenseBillingMap = expenseBillingList.stream().collect(Collectors.toMap(PaymentBilling::getId,
                        e -> expenseBillingList.stream()
                                .filter(expenseBilling -> expenseBilling.getId().equals(e.getId()))
                                .findFirst()
                                .orElse(null)));
                expenseIdList = expenseBillingList.stream().map(PaymentBilling::getOrderId).collect(Collectors.toSet());
                // 查报销订单
                List<Expense> expenseList = expenseMapper.selectBatchIds(expenseIdList);
                Set<String> userIdList = expenseList.stream().map(Expense::getUserId).collect(Collectors.toSet());
                // 查申请人
                List<User> userList = userMapper.selectBatchByIdWithDelete(userIdList);
                userMap = expenseBillingList.stream().collect(Collectors.toMap(PaymentBilling::getId,
                        paymentBilling -> expenseList.stream()
                                .filter(expense -> expense.getId().equals(paymentBilling.getOrderId()))
                                .findFirst()
                                .flatMap(expense -> userList.stream()
                                        .filter(user -> user.getId().equals(expense.getUserId()))
                                        .findFirst())
                                .orElse(null)));
            }
        }
        // 收款
        Map<String, OrderBilling> orderBillingMap = new HashMap<>();
        // 根据账单id获取客户对象
        Map<String, Clients> clientsMap = new HashMap<>();
        if (orderBillingIdList.size() > 0) {
            // 收款账单集合
            List<OrderBilling> orderBillingList = orderBillingMapper.selectBatchIds(orderBillingIdList);
            Set<String> orderIdList = new HashSet<>();
            if (orderBillingList.size() > 0) {
                orderIdList = orderBillingList.stream().map(OrderBilling::getOrderId).collect(Collectors.toSet());
                orderBillingMap = orderBillingList.stream()
                        .collect(Collectors.toMap(OrderBilling::getId, orderBilling -> orderBilling));
                // 根据订单id查询订单列表
                // 订单集合
                List<Order> orderList = orderMapper.selectBatchIdWithDelete(orderIdList, null);
                Set<String> clientsIdList = orderList.stream().map(Order::getClientsId).collect(Collectors.toSet());
                // 根据客户id查询客户列表
                List<Clients> clientsList = clientsMapper.selectBatchByIdWithDelete(clientsIdList);
                // 使用流处理
                clientsMap = orderBillingList.stream().collect(Collectors.toMap(OrderBilling::getId,
                        orderBilling -> orderList.stream()
                                .filter(order -> order.getId().equals(orderBilling.getOrderId()))
                                .findFirst()
                                .flatMap(order -> clientsList.stream()
                                        .filter(clients -> clients.getId().equals(order.getClientsId()))
                                        .findFirst())
                                .orElse(null)));
            }
        }

        List<IncomeExpenditureDetailVo> detailVoList = new ArrayList<>();
        if (detailList.size() > 0) {
            for (IncomeExpenditureDetail detail : detailList) {
                IncomeExpenditureDetailVo detailVo = new IncomeExpenditureDetailVo();
                BeanUtils.copyProperties(detail, detailVo);
                // 交易时间
                detailVo.setTradingHours(DateUtils.YMDHMSFormat(detail.getTradingHours()));
                // 交易对象，交易金额
                if (detail.getDetailType() == 2 && orderBillingMap.size() > 0) {
                    // 收款
                    detailVo.setTradingObject(clientsMap.get(detail.getExpenseId()).getName());
                    detailVo.setAmount(orderBillingMap.get(detail.getExpenseId()).getFundsReceived());
                } else if (detail.getDetailType() == 1 && expenseBillingMap.size() > 0) {
                    // 报销
                    detailVo.setTradingObject(userMap.get(detail.getExpenseId()).getNickName());
                    detailVo.setAmount(expenseBillingMap.get(detail.getExpenseId()).getPaymentAmount());
                } else if (detail.getDetailType() == 0 && paymentBillingMap.size() > 0) {
                    // 付款
                    detailVo.setTradingObject(suppliersMap.get(detail.getExpenseId()).getSuppliersName());
                    detailVo.setAmount(paymentBillingMap.get(detail.getExpenseId()).getPaymentAmount());
                }
                detailVoList.add(detailVo);
            }
        }
        Map<String, Object> map = new HashMap<>();
        map.put("total", detailPage.getTotal());
        map.put("detailVoList", detailVoList);
        return Result.success("查询成功", map);
    }

    @Override
    public Result updateDetailRemark(IncomeExpenditureDetailDto detailDto) {
        if (detailDto == null || (detailDto.getId() == null || detailDto.getId().isEmpty())) {
            return new Result(HttpStatus.BAD_REQUEST, "缺少参数");
        }
        // 查询是否有该账单明细
        IncomeExpenditureDetail detail = detailMapper.selectById(detailDto.getId());
        if (detail == null) {
            return new Result(HttpStatus.BAD_REQUEST, "该账单明细不存在");
        }
        // 修改备注
        if (detailDto.getRemark() != null) {
            detail.setRemark(detailDto.getRemark());
        }
        LambdaUpdateWrapper<IncomeExpenditureDetail> detailLUW = new LambdaUpdateWrapper<>();
        detailLUW.eq(IncomeExpenditureDetail::getId, detail.getId())
                .set(IncomeExpenditureDetail::getRemark, detail.getRemark());
        detailMapper.update(null, detailLUW);
        return Result.success("修改成功");
    }
}
